<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  
  <title>WEI BLOG</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  
  
  
    <link rel="alternate" href="/wei-blog/atom.xml" title="WEI BLOG" type="application/atom+xml">
  
  
    <link rel="shortcut icon" href="/wei-blog/favicon.png">
  
  
    
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/typeface-source-code-pro@0.0.71/index.min.css">

  
  
<link rel="stylesheet" href="/wei-blog/css/style.css">

  
  
  
  
<meta name="generator" content="Hexo 6.3.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a id="logo">WEI BLOG</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        
          <a class="main-nav-link" href="/wei-blog/."><i class="fa fa-home"></i> 首页</a>
        
          <a class="main-nav-link" href="/wei-blog/archives/"><i class="fa fa-archive"></i> 归档</a>
        
      </nav>
    </div>
    <div id="search-form">
      <div id="result-mask" class="hide"></div>
      <label><input id="search-key" type="text" autocomplete="off" placeholder="搜索"></label>
      <div id="result-wrap" class="hide">
        <div id="search-result"></div>
      </div>
      <div class="hide">
        <template id="search-tpl">
          <div class="item">
            <a href="/{path}" title="{title}">
              <div class="title">{title}</div>
              <!-- <div class="time">{date}</div> -->
              <div class="tags">{tags}</div>
            </a>
          </div>
        </template>
      </div>
    </div>
  </div>
</header>

      <div class="outer">
        <section id="main">
  <article id="post-基于Redis的分布式锁" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/wei-blog/source/%E5%9F%BA%E4%BA%8ERedis%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81/">基于Redis的分布式锁</a>
    </h1>
  


      </header>
    
    <div class="article-meta">
      
      <!-- <span class="article-date">
  <i class="fa fa-date"></i>
  <time class="dt-published" datetime="2023-02-08T14:48:34.000Z" itemprop="datePublished">2023年02月08日</time>
</span> -->
      
  <div class="article-category">
    <i class="fa fa-classify"></i>
    <a class="article-category-link" href="/wei-blog/categories/Redis/">Redis</a>
  </div>

      
      
<!-- <a href="/wei-blog/source/%E5%9F%BA%E4%BA%8ERedis%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81/#comments" class="article-comment-link">
  
  <i class="fa fa-commt"></i>
  留言
</a> -->


    </div>
    <div class="e-content article-entry" itemprop="articleBody">
      
        <p>删除的锁不为当前线程创建的锁导致的并发问题</p>
<p><img src="https://gitee.com/xueweitao/images/raw/master/%E5%9F%BA%E4%BA%8EReids%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81-%E9%94%81%E5%88%A0%E9%99%A4%E9%97%AE%E9%A2%98-2023-2-822:51:15.png" alt="基于Redis的分布式锁-锁删除问题"></p>
<p>使用 <code>setnx</code> 命令创建锁并设置过期时间，防止服务宕机时，锁一直存在，并设置值为当前线程ID，以此在删除锁时进行判断，保证删除的锁为当前线程创建的锁，防止多个线程并发运行。</p>
<p>使用 lua 脚本来执行判断锁和删除锁的操作，以此来保证原子性，防止判断锁后执行删除操作时，误删其它线程的锁。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SimpleRedisLock</span> <span class="keyword">implements</span> <span class="title class_">ILock</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> StringRedisTemplate stringRedisTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">SimpleRedisLock</span><span class="params">(String name, StringRedisTemplate stringRedisTemplate)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">        <span class="built_in">this</span>.stringRedisTemplate = stringRedisTemplate;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 锁的前缀</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">KEY_PREFIX</span> <span class="operator">=</span> <span class="string">&quot;lock:&quot;</span>;</span><br><span class="line">    <span class="comment">// 获取UUID防止线程ID重复</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">ID_PREFIX</span> <span class="operator">=</span> UUID.randomUUID().toString(<span class="literal">true</span>) + <span class="string">&quot;-&quot;</span>;</span><br><span class="line">    <span class="comment">// 删除锁lua脚本</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> DefaultRedisScript&lt;Long&gt; UNLOCK_SCRIPT;</span><br><span class="line">    <span class="comment">// 脚本初始化</span></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        UNLOCK_SCRIPT = <span class="keyword">new</span> <span class="title class_">DefaultRedisScript</span>&lt;&gt;();</span><br><span class="line">        <span class="comment">// 脚本位置</span></span><br><span class="line">        UNLOCK_SCRIPT.setLocation(<span class="keyword">new</span> <span class="title class_">ClassPathResource</span>(<span class="string">&quot;unlock.lua&quot;</span>));</span><br><span class="line">        <span class="comment">// 设置返回类型</span></span><br><span class="line">        UNLOCK_SCRIPT.setResultType(Long.class);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">tryLock</span><span class="params">(<span class="type">long</span> timeoutSec)</span> &#123;</span><br><span class="line">        <span class="comment">// 获取线程标示</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">threadId</span> <span class="operator">=</span> ID_PREFIX + Thread.currentThread().getId();</span><br><span class="line">        <span class="comment">// 获取锁</span></span><br><span class="line">        <span class="type">Boolean</span> <span class="variable">success</span> <span class="operator">=</span> stringRedisTemplate.opsForValue()</span><br><span class="line">                .setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);</span><br><span class="line">        <span class="keyword">return</span> Boolean.TRUE.equals(success);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">unlock</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 使用lua脚本保证获取锁和删除锁的原子性</span></span><br><span class="line">        stringRedisTemplate.execute(</span><br><span class="line">                UNLOCK_SCRIPT,</span><br><span class="line">                Collections.singletonList(KEY_PREFIX + name),</span><br><span class="line">                ID_PREFIX + Thread.currentThread().getId());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 比较线程标示与锁中的标示是否一致</span></span><br><span class="line"><span class="keyword">if</span>(redis.call(<span class="string">&#x27;get&#x27;</span>, KEYS[<span class="number">1</span>]) ==  ARGV[<span class="number">1</span>]) <span class="keyword">then</span></span><br><span class="line">    <span class="comment">-- 释放锁</span></span><br><span class="line">    <span class="keyword">return</span> redis.call(<span class="string">&#x27;del&#x27;</span>, KEYS[<span class="number">1</span>])</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span></span><br></pre></td></tr></table></figure>
        
        
      
    </div>
    <footer class="article-footer">
      
        <div class="article-tag-wrap">
          

          
          


        </div>
      
      <!--  -->
      <!--  -->
    </footer>
  </div>
</article>


  <article id="post-SpringBoot实现接口限流" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/wei-blog/source/SpringBoot%E5%AE%9E%E7%8E%B0%E6%8E%A5%E5%8F%A3%E9%99%90%E6%B5%81/">SpringBoot实现接口限流</a>
    </h1>
  


      </header>
    
    <div class="article-meta">
      
      <!-- <span class="article-date">
  <i class="fa fa-date"></i>
  <time class="dt-published" datetime="2023-02-08T08:16:34.000Z" itemprop="datePublished">2023年02月08日</time>
</span> -->
      
  <div class="article-category">
    <i class="fa fa-classify"></i>
    <a class="article-category-link" href="/wei-blog/categories/SpringBoot/">SpringBoot</a>
  </div>

      
      
<!-- <a href="/wei-blog/source/SpringBoot%E5%AE%9E%E7%8E%B0%E6%8E%A5%E5%8F%A3%E9%99%90%E6%B5%81/#comments" class="article-comment-link">
  
  <i class="fa fa-commt"></i>
  留言
</a> -->


    </div>
    <div class="e-content article-entry" itemprop="articleBody">
      
        
        
        
      
    </div>
    <footer class="article-footer">
      
        <div class="article-tag-wrap">
          

          
          


        </div>
      
      <!--  -->
      <!--  -->
    </footer>
  </div>
</article>


  <article id="post-缓存穿透、缓存雪崩、缓存击穿" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-inner">
    
    
    <div class="article-meta">
      
      <!-- <span class="article-date">
  <i class="fa fa-date"></i>
  <time class="dt-published" datetime="2023-02-08T06:57:21.450Z" itemprop="datePublished">2023年02月08日</time>
</span> -->
      
      
      
<!-- <a href="/wei-blog/source/%E7%BC%93%E5%AD%98%E7%A9%BF%E9%80%8F%E3%80%81%E7%BC%93%E5%AD%98%E9%9B%AA%E5%B4%A9%E3%80%81%E7%BC%93%E5%AD%98%E5%87%BB%E7%A9%BF/#comments" class="article-comment-link">
  
  <i class="fa fa-commt"></i>
  留言
</a> -->


    </div>
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="缓存穿透"><a href="#缓存穿透" class="headerlink" title="缓存穿透"></a>缓存穿透</h1><blockquote>
<p>用户请求的数据在缓存中和数据库中都不存在，不断发起这样的请求，给数据库带来巨大压力</p>
</blockquote>
<h2 id="解决方法"><a href="#解决方法" class="headerlink" title="解决方法"></a>解决方法</h2><h3 id="缓存空对象"><a href="#缓存空对象" class="headerlink" title="缓存空对象"></a>缓存空对象</h3><blockquote>
<p>对查询结果为空的对象也进行缓存</p>
</blockquote>
<h4 id="代码示例"><a href="#代码示例" class="headerlink" title="代码示例"></a>代码示例</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> Forum <span class="title function_">getForumDetail</span><span class="params">(<span class="type">int</span> forumId)</span> &#123;</span><br><span class="line">    Forum forum;</span><br><span class="line">    <span class="type">String</span> <span class="variable">redisKey</span> <span class="operator">=</span> RedisKey.FORUM_DETAIL_PREFIX + forumId;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 查询缓存</span></span><br><span class="line">    <span class="type">Object</span> <span class="variable">originalForum</span> <span class="operator">=</span> redisUtil.get(redisKey);</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 缓存不存在</span></span><br><span class="line">    <span class="keyword">if</span> (originalForum == <span class="literal">null</span>) &#123;</span><br><span class="line">        <span class="comment">// 缓存不存在，查询论坛详情</span></span><br><span class="line">        forum = lambdaQuery()</span><br><span class="line">                .select(Forum::getName, Forum::getDescription, Forum::getIcon)</span><br><span class="line">                .eq(Forum::getId, forumId)</span><br><span class="line">                .one();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 判断论坛是否存在</span></span><br><span class="line">        <span class="keyword">if</span> (forum == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="comment">// 论坛不存在，缓存空字符串30秒</span></span><br><span class="line">            log.info(<span class="string">&quot;论坛不存在缓存空字符串 --- &quot;</span> + forumId);</span><br><span class="line">            redisUtil.setWithSecond(redisKey, <span class="string">&quot;&quot;</span>, <span class="number">30</span>);</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Forum</span>();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 设置头像链接</span></span><br><span class="line">        forum.setIcon(CosUtil.getIconLink(forum.getIcon()));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 保存论坛详情到缓存</span></span><br><span class="line">        log.info(<span class="string">&quot;添加缓存 --- &quot;</span> + forum);</span><br><span class="line">        redisUtil.setWithSecond(redisKey, forum, <span class="number">1800</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> forum;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 判断是否为空缓存</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="string">&quot;&quot;</span>.equals(originalForum)) &#123;</span><br><span class="line">        log.info(<span class="string">&quot;缓存为空字符串 --- &quot;</span> + forumId);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Forum</span>();</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        log.info(<span class="string">&quot;缓存为存在对象 --- &quot;</span> + originalForum);</span><br><span class="line">        <span class="keyword">return</span> (Forum) originalForum;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="布隆过滤器"><a href="#布隆过滤器" class="headerlink" title="布隆过滤器"></a>布隆过滤器</h3><blockquote>
<p>将所有可能存在的数据哈希到一个足够大的 bitmap 中，一个一定不存在的数据会被这个 bitmap 拦截掉</p>
</blockquote>
<h1 id="缓存雪崩"><a href="#缓存雪崩" class="headerlink" title="缓存雪崩"></a>缓存雪崩</h1><blockquote>
<p>同一时间段内大量的key同时失效或者Redis服务宕机，导致大量请求到达服务器</p>
</blockquote>
<h2 id="解决方法-1"><a href="#解决方法-1" class="headerlink" title="解决方法"></a>解决方法</h2><h3 id="key-添加-ttl-随机值"><a href="#key-添加-ttl-随机值" class="headerlink" title="key 添加 ttl 随机值"></a>key 添加 ttl 随机值</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 保存论坛详情到缓存并添加随机数，防止缓存雪崩</span></span><br><span class="line">redisUtil.setWithSecond(redisKey, forum, <span class="number">1800</span> + <span class="keyword">new</span> <span class="title class_">Random</span>().nextInt(<span class="number">101</span>));</span><br></pre></td></tr></table></figure>

<h3 id="使用-Redis-集群"><a href="#使用-Redis-集群" class="headerlink" title="使用 Redis 集群"></a>使用 Redis 集群</h3><h1 id="缓存击穿"><a href="#缓存击穿" class="headerlink" title="缓存击穿"></a>缓存击穿</h1><blockquote>
<p>缓存击穿问题也叫热点key问题，就是一个高并发访问且缓存重建业务复杂的key突然失效，导致大量请求到达数据库</p>
</blockquote>
<h2 id="解决方法-2"><a href="#解决方法-2" class="headerlink" title="解决方法"></a>解决方法</h2><h3 id="互斥锁"><a href="#互斥锁" class="headerlink" title="互斥锁"></a>互斥锁</h3><blockquote>
<p>优点</p>
<ul>
<li><p>没有额外的内存消耗</p>
</li>
<li><p>保证一致性</p>
</li>
<li><p>实现简单</p>
</li>
</ul>
<p>缺点</p>
<ul>
<li><p>线程需要等待，性能受影响</p>
</li>
<li><p>可能有死锁风险</p>
</li>
</ul>
</blockquote>
<p><img src="https://gitee.com/xueweitao/images/raw/master/%E7%BC%93%E5%AD%98%E5%87%BB%E7%A9%BF-%E4%BA%92%E6%96%A5%E9%94%81-2023-2-814:53:58.png" alt="缓存击穿-互斥锁"></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> &lt;R, ID&gt; R <span class="title function_">queryWithMutex</span><span class="params">(</span></span><br><span class="line"><span class="params">        String keyPrefix, ID id, Class&lt;R&gt; type, Function&lt;ID, R&gt; dbFallback, Long time, TimeUnit unit)</span> &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">key</span> <span class="operator">=</span> keyPrefix + id;</span><br><span class="line">    <span class="comment">// 1.从redis查询商铺缓存</span></span><br><span class="line">    <span class="type">String</span> <span class="variable">shopJson</span> <span class="operator">=</span> stringRedisTemplate.opsForValue().get(key);</span><br><span class="line">    <span class="comment">// 2.判断是否存在</span></span><br><span class="line">    <span class="keyword">if</span> (StrUtil.isNotBlank(shopJson)) &#123;</span><br><span class="line">        <span class="comment">// 3.存在，直接返回</span></span><br><span class="line">        <span class="keyword">return</span> JSONUtil.toBean(shopJson, type);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 判断命中的是否是空值</span></span><br><span class="line">    <span class="keyword">if</span> (shopJson != <span class="literal">null</span>) &#123;</span><br><span class="line">        <span class="comment">// 返回一个错误信息</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 4.实现缓存重建</span></span><br><span class="line">    <span class="comment">// 4.1.获取互斥锁</span></span><br><span class="line">    <span class="type">String</span> <span class="variable">lockKey</span> <span class="operator">=</span> LOCK_SHOP_KEY + id;</span><br><span class="line">    <span class="type">R</span> <span class="variable">r</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="type">boolean</span> <span class="variable">isLock</span> <span class="operator">=</span> tryLock(lockKey);</span><br><span class="line">        <span class="comment">// 4.2.判断是否获取成功</span></span><br><span class="line">        <span class="keyword">if</span> (!isLock) &#123;</span><br><span class="line">            <span class="comment">// 4.3.获取锁失败，休眠并重试</span></span><br><span class="line">            Thread.sleep(<span class="number">50</span>);</span><br><span class="line">            <span class="keyword">return</span> queryWithMutex(keyPrefix, id, type, dbFallback, time, unit);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 4.4.获取锁成功，根据id查询数据库</span></span><br><span class="line">        r = dbFallback.apply(id);</span><br><span class="line">        <span class="comment">// 5.不存在，返回错误</span></span><br><span class="line">        <span class="keyword">if</span> (r == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="comment">// 将空值写入redis</span></span><br><span class="line">            stringRedisTemplate.opsForValue().set(key, <span class="string">&quot;&quot;</span>, CACHE_NULL_TTL, TimeUnit.MINUTES);</span><br><span class="line">            <span class="comment">// 返回错误信息</span></span><br><span class="line">            <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 6.存在，写入redis</span></span><br><span class="line">        <span class="built_in">this</span>.set(key, r, time, unit);</span><br><span class="line">    &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(e);</span><br><span class="line">    &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">        <span class="comment">// 7.释放锁</span></span><br><span class="line">        unlock(lockKey);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 8.返回</span></span><br><span class="line">    <span class="keyword">return</span> r;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 获取锁和释放锁</span></span><br><span class="line"><span class="keyword">private</span> <span class="type">boolean</span> <span class="title function_">tryLock</span><span class="params">(String key)</span> &#123;</span><br><span class="line">    <span class="type">Boolean</span> <span class="variable">flag</span> <span class="operator">=</span> stringRedisTemplate.opsForValue().setIfAbsent(key, <span class="string">&quot;1&quot;</span>, <span class="number">10</span>, TimeUnit.SECONDS);</span><br><span class="line">    <span class="keyword">return</span> BooleanUtil.isTrue(flag);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">unlock</span><span class="params">(String key)</span> &#123;</span><br><span class="line">    stringRedisTemplate.delete(key);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="逻辑过期"><a href="#逻辑过期" class="headerlink" title="逻辑过期"></a>逻辑过期</h3><blockquote>
<p>优点</p>
<ul>
<li>线程无需等待，性能较好</li>
</ul>
<p>缺点</p>
<ul>
<li><p>不保证一致性</p>
</li>
<li><p>有额外内存消耗</p>
</li>
<li><p>实现复杂</p>
</li>
</ul>
</blockquote>
<p><img src="https://gitee.com/xueweitao/images/raw/master/%E7%BC%93%E5%AD%98%E5%87%BB%E7%A9%BF-%E9%80%BB%E8%BE%91%E8%BF%87%E6%9C%9F-2023-2-814:56:07.png" alt="缓存击穿-逻辑过期"></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> &lt;R, ID&gt; R <span class="title function_">queryWithLogicalExpire</span><span class="params">(</span></span><br><span class="line"><span class="params">        String keyPrefix, ID id, Class&lt;R&gt; type, Function&lt;ID, R&gt; dbFallback, Long time, TimeUnit unit)</span> &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">key</span> <span class="operator">=</span> keyPrefix + id;</span><br><span class="line">    <span class="comment">// 1.从redis查询商铺缓存</span></span><br><span class="line">    <span class="type">String</span> <span class="variable">json</span> <span class="operator">=</span> stringRedisTemplate.opsForValue().get(key);</span><br><span class="line">    <span class="comment">// 2.判断是否存在</span></span><br><span class="line">    <span class="keyword">if</span> (StrUtil.isBlank(json)) &#123;</span><br><span class="line">        <span class="comment">// 3.存在，直接返回</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 4.命中，需要先把json反序列化为对象</span></span><br><span class="line">    <span class="type">RedisData</span> <span class="variable">redisData</span> <span class="operator">=</span> JSONUtil.toBean(json, RedisData.class);</span><br><span class="line">    <span class="type">R</span> <span class="variable">r</span> <span class="operator">=</span> JSONUtil.toBean((JSONObject) redisData.getData(), type);</span><br><span class="line">    <span class="type">LocalDateTime</span> <span class="variable">expireTime</span> <span class="operator">=</span> redisData.getExpireTime();</span><br><span class="line">    <span class="comment">// 5.判断是否过期</span></span><br><span class="line">    <span class="keyword">if</span>(expireTime.isAfter(LocalDateTime.now())) &#123;</span><br><span class="line">        <span class="comment">// 5.1.未过期，直接返回店铺信息</span></span><br><span class="line">        <span class="keyword">return</span> r;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 5.2.已过期，需要缓存重建</span></span><br><span class="line">    <span class="comment">// 6.缓存重建</span></span><br><span class="line">    <span class="comment">// 6.1.获取互斥锁</span></span><br><span class="line">    <span class="type">String</span> <span class="variable">lockKey</span> <span class="operator">=</span> LOCK_SHOP_KEY + id;</span><br><span class="line">    <span class="type">boolean</span> <span class="variable">isLock</span> <span class="operator">=</span> tryLock(lockKey);</span><br><span class="line">    <span class="comment">// 6.2.判断是否获取锁成功</span></span><br><span class="line">    <span class="keyword">if</span> (isLock)&#123;</span><br><span class="line">        <span class="comment">// 6.3.成功，开启独立线程，实现缓存重建</span></span><br><span class="line">        CACHE_REBUILD_EXECUTOR.submit(() -&gt; &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="comment">// 查询数据库</span></span><br><span class="line">                <span class="type">R</span> <span class="variable">newR</span> <span class="operator">=</span> dbFallback.apply(id);</span><br><span class="line">                <span class="comment">// 重建缓存</span></span><br><span class="line">                <span class="built_in">this</span>.setWithLogicalExpire(key, newR, time, unit);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(e);</span><br><span class="line">            &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">                <span class="comment">// 释放锁</span></span><br><span class="line">                unlock(lockKey);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 6.4.返回过期的商铺信息</span></span><br><span class="line">    <span class="keyword">return</span> r;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setWithLogicalExpire</span><span class="params">(String key, Object value, Long time, TimeUnit unit)</span> &#123;</span><br><span class="line">    <span class="comment">// 设置逻辑过期</span></span><br><span class="line">    <span class="type">RedisData</span> <span class="variable">redisData</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">RedisData</span>();</span><br><span class="line">    redisData.setData(value);</span><br><span class="line">    redisData.setExpireTime(LocalDateTime.now().plusSeconds(unit.toSeconds(time)));</span><br><span class="line">    <span class="comment">// 写入Redis</span></span><br><span class="line">    stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(redisData));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RedisData</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> LocalDateTime expireTime;</span><br><span class="line">    <span class="keyword">private</span> Object data;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
        
        
      
    </div>
    <footer class="article-footer">
      
        <div class="article-tag-wrap">
          

          
          


        </div>
      
      <!--  -->
      <!--  -->
    </footer>
  </div>
</article>


  <article id="post-SpringBoot整合RabbitMQ" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/wei-blog/source/SpringBoot%E6%95%B4%E5%90%88RabbitMQ/">SpringBoot整合RabbitMQ</a>
    </h1>
  


      </header>
    
    <div class="article-meta">
      
      <!-- <span class="article-date">
  <i class="fa fa-date"></i>
  <time class="dt-published" datetime="2023-02-07T12:52:34.000Z" itemprop="datePublished">2023年02月07日</time>
</span> -->
      
  <div class="article-category">
    <i class="fa fa-classify"></i>
    <a class="article-category-link" href="/wei-blog/categories/SpringBoot/">SpringBoot</a> > <a class="article-category-link" href="/wei-blog/categories/SpringBoot/RabbitMQ/">RabbitMQ</a>
  </div>

      
      
<!-- <a href="/wei-blog/source/SpringBoot%E6%95%B4%E5%90%88RabbitMQ/#comments" class="article-comment-link">
  
  <i class="fa fa-commt"></i>
  留言
</a> -->


    </div>
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="导入依赖"><a href="#导入依赖" class="headerlink" title="导入依赖"></a>导入依赖</h1><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-amqp<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h1 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h1><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring.rabbitmq.host</span>=<span class="string">192.168.31.161</span></span><br><span class="line"><span class="attr">spring.rabbitmq.port</span>=<span class="string">5672</span></span><br><span class="line"><span class="attr">spring.rabbitmq.username</span>=<span class="string">wei_forum</span></span><br><span class="line"><span class="attr">spring.rabbitmq.password</span>=<span class="string">wei_forum</span></span><br><span class="line"><span class="attr">spring.rabbitmq.virtual-host</span>=<span class="string">wei_forum</span></span><br></pre></td></tr></table></figure>

<h1 id="简单使用"><a href="#简单使用" class="headerlink" title="简单使用"></a>简单使用</h1><blockquote>
<p>消费者</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@RabbitListener(queuesToDeclare = @Queue(&quot;hello&quot;))</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HelloComponent</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 接受到消息时调用此方法</span></span><br><span class="line">    <span class="meta">@RabbitHandler</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">receive</span><span class="params">(String message)</span> &#123;</span><br><span class="line">        System.out.println(message);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li><code>@RabbitListener</code>: 定义一个消费者<ul>
<li><code>queuesToDeclare = @Queue(&quot;hello&quot;)</code>和hello队列绑定，当队列不存在时创建此队列</li>
</ul>
</li>
<li><code>@RabbitHandler</code>指定此队列的消费方法</li>
</ul>
<blockquote>
<p>发送者</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Resource</span></span><br><span class="line">RabbitTemplate rabbitTemplate;</span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">contextLoads</span><span class="params">()</span> &#123;</span><br><span class="line">    rabbitTemplate.convertAndSend(<span class="string">&quot;hello&quot;</span>, <span class="string">&quot;hello world&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h1 id="工作队列"><a href="#工作队列" class="headerlink" title="工作队列"></a>工作队列</h1><blockquote>
<p>消费者</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WorkCustomer</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RabbitListener(queuesToDeclare = @Queue(&quot;work&quot;))</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">receive1</span><span class="params">(String message)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;receive1: &quot;</span> + message);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RabbitListener(queuesToDeclare = @Queue(&quot;work&quot;))</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">receive2</span><span class="params">(String message)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;receive2: &quot;</span> + message);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>发送者</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Resource</span></span><br><span class="line">RabbitTemplate rabbitTemplate;</span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">contextLoads</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>; i &lt;= <span class="number">20</span>; i++) &#123;</span><br><span class="line">        rabbitTemplate.convertAndSend(<span class="string">&quot;work&quot;</span>, <span class="string">&quot;hello world &quot;</span> + i);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h1 id="广播模式"><a href="#广播模式" class="headerlink" title="广播模式"></a>广播模式</h1><blockquote>
<p>消费者</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">FanoutCustomer</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RabbitListener(bindings = &#123;</span></span><br><span class="line"><span class="meta">            @QueueBinding(</span></span><br><span class="line"><span class="meta">                    // 创建临时队列</span></span><br><span class="line"><span class="meta">                    value = @Queue,</span></span><br><span class="line"><span class="meta">                    // 绑定交换机</span></span><br><span class="line"><span class="meta">                    exchange = @Exchange(value = &quot;logs&quot;, type = &quot;fanout&quot;)</span></span><br><span class="line"><span class="meta">            )</span></span><br><span class="line"><span class="meta">    &#125;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">receive1</span><span class="params">(String message)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;receive1: &quot;</span> + message);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="meta">@RabbitListener(bindings = &#123;</span></span><br><span class="line"><span class="meta">            @QueueBinding(</span></span><br><span class="line"><span class="meta">                    // 创建临时队列</span></span><br><span class="line"><span class="meta">                    value = @Queue,</span></span><br><span class="line"><span class="meta">                    // 绑定交换机</span></span><br><span class="line"><span class="meta">                    exchange = @Exchange(value = &quot;logs&quot;, type = &quot;fanout&quot;)</span></span><br><span class="line"><span class="meta">            )</span></span><br><span class="line"><span class="meta">    &#125;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">receive2</span><span class="params">(String message)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;receive2: &quot;</span> + message);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>发送者</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Resource</span></span><br><span class="line">RabbitTemplate rabbitTemplate;</span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">contextLoads</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>; i &lt;= <span class="number">5</span>; i++) &#123;</span><br><span class="line">        rabbitTemplate.convertAndSend(<span class="string">&quot;logs&quot;</span>, <span class="string">&quot;&quot;</span>, <span class="string">&quot;hello world &quot;</span> + i);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h1 id="路由模式"><a href="#路由模式" class="headerlink" title="路由模式"></a>路由模式</h1><blockquote>
<p>消费者</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RouteCustomer</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RabbitListener(bindings = &#123;</span></span><br><span class="line"><span class="meta">            @QueueBinding(</span></span><br><span class="line"><span class="meta">                    // 创建临时队列</span></span><br><span class="line"><span class="meta">                    value = @Queue,</span></span><br><span class="line"><span class="meta">                    // 绑定交换机</span></span><br><span class="line"><span class="meta">                    exchange = @Exchange(value = &quot;directs&quot;, type = &quot;direct&quot;),</span></span><br><span class="line"><span class="meta">                    key = &#123;&quot;info&quot;, &quot;error&quot;, &quot;warn&quot;&#125;</span></span><br><span class="line"><span class="meta">            )</span></span><br><span class="line"><span class="meta">    &#125;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">receive1</span><span class="params">(String message)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;receive1: &quot;</span> + message);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="meta">@RabbitListener(bindings = &#123;</span></span><br><span class="line"><span class="meta">            @QueueBinding(</span></span><br><span class="line"><span class="meta">                    // 创建临时队列</span></span><br><span class="line"><span class="meta">                    value = @Queue,</span></span><br><span class="line"><span class="meta">                    // 绑定交换机</span></span><br><span class="line"><span class="meta">                    exchange = @Exchange(value = &quot;directs&quot;, type = &quot;direct&quot;),</span></span><br><span class="line"><span class="meta">                    key = &#123;&quot;error&quot;&#125;</span></span><br><span class="line"><span class="meta">            )</span></span><br><span class="line"><span class="meta">    &#125;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">receive2</span><span class="params">(String message)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;receive2: &quot;</span> + message);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>发送者</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Resource</span></span><br><span class="line">RabbitTemplate rabbitTemplate;</span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">contextLoads</span><span class="params">()</span> &#123;</span><br><span class="line">    rabbitTemplate.convertAndSend(<span class="string">&quot;directs&quot;</span>, <span class="string">&quot;info&quot;</span>, <span class="string">&quot;hello world &quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h1 id="订阅模式（动态路由）"><a href="#订阅模式（动态路由）" class="headerlink" title="订阅模式（动态路由）"></a>订阅模式（动态路由）</h1><blockquote>
<p>消费者</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TopicCustomer</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RabbitListener(bindings = &#123;</span></span><br><span class="line"><span class="meta">            @QueueBinding(</span></span><br><span class="line"><span class="meta">                    // 创建临时队列</span></span><br><span class="line"><span class="meta">                    value = @Queue,</span></span><br><span class="line"><span class="meta">                    // 绑定交换机</span></span><br><span class="line"><span class="meta">                    exchange = @Exchange(value = &quot;topics&quot;, type = &quot;topic&quot;),</span></span><br><span class="line"><span class="meta">                    key = &#123;&quot;user.*&quot;&#125;</span></span><br><span class="line"><span class="meta">            )</span></span><br><span class="line"><span class="meta">    &#125;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">receive1</span><span class="params">(String message)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;receive1: &quot;</span> + message);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="meta">@RabbitListener(bindings = &#123;</span></span><br><span class="line"><span class="meta">            @QueueBinding(</span></span><br><span class="line"><span class="meta">                    // 创建临时队列</span></span><br><span class="line"><span class="meta">                    value = @Queue,</span></span><br><span class="line"><span class="meta">                    // 绑定交换机</span></span><br><span class="line"><span class="meta">                    exchange = @Exchange(value = &quot;topics&quot;, type = &quot;topic&quot;),</span></span><br><span class="line"><span class="meta">                    key = &#123;&quot;user.#&quot;&#125;</span></span><br><span class="line"><span class="meta">            )</span></span><br><span class="line"><span class="meta">    &#125;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">receive2</span><span class="params">(String message)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;receive2: &quot;</span> + message);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>多个单词之间用 . 分割</strong></p>
<p>*** 匹配一个单词**</p>
<p><strong># 匹配多个单词</strong></p>
<blockquote>
<p>发送者</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Resource</span></span><br><span class="line">RabbitTemplate rabbitTemplate;</span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">contextLoads</span><span class="params">()</span> &#123;</span><br><span class="line">    rabbitTemplate.convertAndSend(<span class="string">&quot;topics&quot;</span>, <span class="string">&quot;user.name.password&quot;</span>, <span class="string">&quot;hello world &quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

        
        
      
    </div>
    <footer class="article-footer">
      
        <div class="article-tag-wrap">
          

          
          


        </div>
      
      <!--  -->
      <!--  -->
    </footer>
  </div>
</article>


  <article id="post-Redis之ZSet" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-inner">
    
    
    <div class="article-meta">
      
      <!-- <span class="article-date">
  <i class="fa fa-date"></i>
  <time class="dt-published" datetime="2023-02-07T12:17:34.000Z" itemprop="datePublished">2023年02月07日</time>
</span> -->
      
  <div class="article-category">
    <i class="fa fa-classify"></i>
    <a class="article-category-link" href="/wei-blog/categories/Redis/">Redis</a>
  </div>

      
      
<!-- <a href="/wei-blog/source/Redis%E4%B9%8BZSet/#comments" class="article-comment-link">
  
  <i class="fa fa-commt"></i>
  留言
</a> -->


    </div>
    <div class="e-content article-entry" itemprop="articleBody">
      
        <blockquote>
<p>zset 的每个元素都会关联一个 double 类型的分数（score）。Redis 就是通过分数来为集合中的成员进行从小到大的排序。</p>
<p>有序集合的成员是唯一的，但是对应的分数 （score）是可以重复的。</p>
</blockquote>
<h1 id="操作"><a href="#操作" class="headerlink" title="操作"></a>操作</h1><blockquote>
<p>添加一个或多个元素</p>
<p><code>zadd key score01 element01 score02 element02...</code></p>
</blockquote>
<blockquote>
<p>获取元素的分数</p>
<p><code>zscore key element</code></p>
</blockquote>
<blockquote>
<p>获取元素的个数</p>
<p><code>zcard key</code></p>
</blockquote>
<blockquote>
<p>删除一个或多个元素</p>
<p><code>zrem key element01 element02...</code></p>
</blockquote>
<blockquote>
<p>范围查询</p>
<p>从小到大</p>
<p><code>zrange key start_element_index end_element_index withscores</code></p>
<p>从大到小</p>
<p><code>zrevrange key start_element_index end_element_index withscores</code></p>
<p><code>withscores</code>附带分数，不加则没有分数</p>
</blockquote>
<blockquote>
<p>按照分数范围查询</p>
<p>从小到大</p>
<p><code>zrangebyscore key min max</code></p>
<p>从大到小</p>
<p><code>zrevrangebyscore key max min</code></p>
<p>min max 范围包括 min 和 max</p>
<p>使用 <code>(</code> 来表示不包括 <code>(min max</code> <code> (min (max</code></p>
</blockquote>
<blockquote>
<p>按照范围删除元素</p>
<p><code>zremrangebyrank key start_element_index end_element_index</code></p>
</blockquote>
<blockquote>
<p>按照分数删除</p>
<p><code>zremrangebyscore key start_score end_score</code></p>
</blockquote>
<blockquote>
<p>增加指定元素的分数</p>
<p><code>zincrby key score element</code></p>
</blockquote>
<blockquote>
<p>获取指定分数段的元素个数</p>
<p><code>zcount key score_start score_end</code></p>
</blockquote>
<blockquote>
<p>获取指定元素在集合中的排名</p>
<p>从小到大</p>
<p><code>zrank key element</code></p>
<p>从大到小</p>
<p><code>zrevrank key element</code></p>
<p>排名从0开始</p>
</blockquote>

        
        
      
    </div>
    <footer class="article-footer">
      
        <div class="article-tag-wrap">
          

          
          


        </div>
      
      <!--  -->
      <!--  -->
    </footer>
  </div>
</article>


  <article id="post-RabbitMQ延迟队列" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/wei-blog/source/RabbitMQ%E5%BB%B6%E8%BF%9F%E9%98%9F%E5%88%97/">RabbitMQ延迟队列</a>
    </h1>
  


      </header>
    
    <div class="article-meta">
      
      <!-- <span class="article-date">
  <i class="fa fa-date"></i>
  <time class="dt-published" datetime="2023-02-07T12:00:34.000Z" itemprop="datePublished">2023年02月07日</time>
</span> -->
      
  <div class="article-category">
    <i class="fa fa-classify"></i>
    <a class="article-category-link" href="/wei-blog/categories/RabbitMQ/">RabbitMQ</a>
  </div>

      
      
<!-- <a href="/wei-blog/source/RabbitMQ%E5%BB%B6%E8%BF%9F%E9%98%9F%E5%88%97/#comments" class="article-comment-link">
  
  <i class="fa fa-commt"></i>
  留言
</a> -->


    </div>
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="插件延迟队列"><a href="#插件延迟队列" class="headerlink" title="插件延迟队列"></a>插件延迟队列</h1><p>插件地址：<a target="_blank" rel="noopener" href="https://github.com/rabbitmq/rabbitmq-delayed-message-exchange">https://github.com/rabbitmq/rabbitmq-delayed-message-exchange</a></p>
<h1 id="声明交换机和队列"><a href="#声明交换机和队列" class="headerlink" title="声明交换机和队列"></a>声明交换机和队列</h1><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RabbitDelayConfig</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">DELAY_MSG_QUEUE</span> <span class="operator">=</span> <span class="string">&quot;delay_msg_queue&quot;</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">DELAY_MSG_EXCHANGE</span> <span class="operator">=</span> <span class="string">&quot;delay_msg_exchange&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> Queue <span class="title function_">delayQueue</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Queue</span>(DELAY_MSG_QUEUE, <span class="literal">true</span>, <span class="literal">false</span>, <span class="literal">false</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> CustomExchange <span class="title function_">delayExchange</span><span class="params">()</span> &#123;</span><br><span class="line">        HashMap&lt;String, Object&gt; args = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line">        <span class="comment">// 延迟队列类型</span></span><br><span class="line">        args.put(<span class="string">&quot;x-delayed-type&quot;</span>, <span class="string">&quot;direct&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">CustomExchange</span>(DELAY_MSG_EXCHANGE, <span class="string">&quot;x-delayed-message&quot;</span>, <span class="literal">true</span>, <span class="literal">false</span>, args);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> Binding <span class="title function_">delayBinding</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> BindingBuilder.bind(delayQueue()).to(delayExchange()).with(DELAY_MSG_QUEUE).noargs();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h1 id="发送延迟消息"><a href="#发送延迟消息" class="headerlink" title="发送延迟消息"></a>发送延迟消息</h1><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">Message</span> <span class="variable">message</span> <span class="operator">=</span> MessageBuilder</span><br><span class="line">        .withBody(LocalDateTime.now().toString().getBytes(StandardCharsets.UTF_8))</span><br><span class="line">    	<span class="comment">// 设置延迟时间 毫秒</span></span><br><span class="line">        .setHeader(<span class="string">&quot;x-delay&quot;</span>, <span class="number">10000</span>)</span><br><span class="line">        .build();</span><br><span class="line"></span><br><span class="line">rabbitTemplate.send(RabbitDelayConfig.DELAY_MSG_EXCHANGE, RabbitDelayConfig.DELAY_MSG_QUEUE, message);</span><br></pre></td></tr></table></figure>

<h1 id="监听队列"><a href="#监听队列" class="headerlink" title="监听队列"></a>监听队列</h1><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DelayMsgListener</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RabbitListener(queues = RabbitDelayConfig.DELAY_MSG_QUEUE)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handleMsg</span><span class="params">(String msg)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;msg = &quot;</span> + msg);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
        
        
      
    </div>
    <footer class="article-footer">
      
        <div class="article-tag-wrap">
          

          
          


        </div>
      
      <!--  -->
      <!--  -->
    </footer>
  </div>
</article>


  <article id="post-Redis之Set" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-inner">
    
    
    <div class="article-meta">
      
      <!-- <span class="article-date">
  <i class="fa fa-date"></i>
  <time class="dt-published" datetime="2023-02-07T08:29:34.000Z" itemprop="datePublished">2023年02月07日</time>
</span> -->
      
  <div class="article-category">
    <i class="fa fa-classify"></i>
    <a class="article-category-link" href="/wei-blog/categories/Redis/">Redis</a>
  </div>

      
      
<!-- <a href="/wei-blog/source/Redis%E4%B9%8BSet/#comments" class="article-comment-link">
  
  <i class="fa fa-commt"></i>
  留言
</a> -->


    </div>
    <div class="e-content article-entry" itemprop="articleBody">
      
        <blockquote>
<p>集合只会存储非重复元素</p>
<p>集合以无序方式存储元素</p>
</blockquote>
<h1 id="命令"><a href="#命令" class="headerlink" title="命令"></a>命令</h1><blockquote>
<p>将一个或多个元素添加到集合</p>
<p><code>sadd key element01 element02...</code></p>
</blockquote>
<blockquote>
<p>从集合中移除一个或多个元素</p>
<p><code>srem key emement01 element02...</code></p>
</blockquote>
<blockquote>
<p>将元素从一个集合移动到另一个集合</p>
<p><code>smove source_key target_key element</code></p>
<p>目标集合不存在时会自动创建</p>
</blockquote>
<blockquote>
<p>获取集合中包含的所有元素</p>
<p><code>smembers key</code></p>
</blockquote>
<blockquote>
<p>获取集合包含的元素数量</p>
<p><code>scard key</code></p>
</blockquote>
<blockquote>
<p>检查给定元素是否在集合中</p>
<p><code>sismember key element</code></p>
</blockquote>
<blockquote>
<p>随机获取集合中指定数量的元素</p>
<p><code>srandmember key count</code></p>
<p>count 默认为1</p>
<p>count 大于集合元素数量则返回集合中所有元素</p>
<p>count 值为负数则返回 count 绝对值的个数，并且允许出现重复元素</p>
</blockquote>
<blockquote>
<p>随机从集合中移除指定数量的元素</p>
<p><code>spop key count</code></p>
<p>count 默认为1</p>
</blockquote>
<blockquote>
<p>对集合进行交集运算</p>
<p><code>sinter key1 kye2 ...</code></p>
</blockquote>
<blockquote>
<p>对集合进行交集运算并保存</p>
<p><code>sinterstore save_key key01 key02...</code></p>
</blockquote>
<blockquote>
<p>对集合进行并集运算</p>
<p><code>sunion key01 key02...</code></p>
</blockquote>
<blockquote>
<p>对集合进行并集运算并保存</p>
<p><code>sunionstore save_key key01 key02...</code></p>
</blockquote>
<blockquote>
<p>对集合进行差集运算</p>
<p><code>sdiff key01 key02...</code></p>
</blockquote>
<blockquote>
<p>对集合进行差集运算并保存</p>
<p><code>sdiffstore save_key key01 key02...</code></p>
</blockquote>

        
        
      
    </div>
    <footer class="article-footer">
      
        <div class="article-tag-wrap">
          

          
          


        </div>
      
      <!--  -->
      <!--  -->
    </footer>
  </div>
</article>


  <article id="post-Docker基本使用" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-inner">
    
    
    <div class="article-meta">
      
      <!-- <span class="article-date">
  <i class="fa fa-date"></i>
  <time class="dt-published" datetime="2023-02-07T06:43:34.000Z" itemprop="datePublished">2023年02月07日</time>
</span> -->
      
  <div class="article-category">
    <i class="fa fa-classify"></i>
    <a class="article-category-link" href="/wei-blog/categories/Docker/">Docker</a>
  </div>

      
      
<!-- <a href="/wei-blog/source/Docker%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8/#comments" class="article-comment-link">
  
  <i class="fa fa-commt"></i>
  留言
</a> -->


    </div>
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h1><ul>
<li>安装软件包：<ul>
<li><code>yum install -y yum-utils</code></li>
</ul>
</li>
<li>设置镜像仓库：<ul>
<li><code>yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo</code></li>
</ul>
</li>
<li>安装：<ul>
<li><code>yum install docker-ce docker-ce-cli containerd.io</code></li>
</ul>
</li>
<li>设置镜像加速器<ul>
<li>在&#x2F;etc&#x2F;docker&#x2F;daemon.json中添加 <code>&#123;&quot;registry-mirrors&quot;: [&quot;https://registry.docker-cn.com&quot;]&#125;</code></li>
</ul>
</li>
<li>启动docker：<ul>
<li><code>systemctl start docker</code></li>
</ul>
</li>
</ul>
<h1 id="镜像"><a href="#镜像" class="headerlink" title="镜像"></a>镜像</h1><ul>
<li>列出镜像列表<ul>
<li><code>docker images</code></li>
</ul>
</li>
<li>拉取镜像<ul>
<li><code>docker pull 镜像：版本</code></li>
</ul>
</li>
<li>删除镜像<ul>
<li><code>docker rmi 镜像：版本</code></li>
</ul>
</li>
</ul>
<h1 id="容器"><a href="#容器" class="headerlink" title="容器"></a>容器</h1><blockquote>
<p>运行容器</p>
<p>基本运行: <code>docker run -d --name 容器名 -p 宿主机端口:容器端口 -v 宿主机路径:容器路径 镜像名:版本号</code></p>
<p>特殊参数：</p>
<p>​	-v 宿主机路径:容器路径</p>
<p>​	保证容器时间和宿主机时间一致 -v  &#x2F;etc&#x2F;localtime:&#x2F;etc&#x2F;localtime:ro</p>
<p>redis: <code>docker run -d -p 6379:6379 -e TZ=&quot;Asia/Shanghai&quot; --name redis redis:6.0.7 --requirepass 123456 </code></p>
</blockquote>
<blockquote>
<p>进入容器</p>
<p><code>docker exec -it 容器名|容器id /bin/bash</code></p>
</blockquote>
<blockquote>
<p>停止容器</p>
<p><code>docker stop 容器id</code></p>
</blockquote>
<blockquote>
<p>重启容器</p>
<p><code>docker restart 容器id</code></p>
</blockquote>
<blockquote>
<p>删除容器</p>
<p><code>docker rm -f 容器id</code></p>
</blockquote>
<blockquote>
<p>查看器运行日志</p>
<p><code>docker logs 容器id</code></p>
</blockquote>
<blockquote>
<p>复制主机文件到容器</p>
<p><code>docker cp /etc/localtime 容器ID:/etc/localtime</code></p>
</blockquote>
<h1 id="DockerFile"><a href="#DockerFile" class="headerlink" title="DockerFile"></a>DockerFile</h1><blockquote>
<p>dockerfile就是用来构建docker镜像的构建文件，命令参数脚本</p>
</blockquote>
<ul>
<li><p>保留字指令</p>
<ul>
<li>FROM： 引入基础镜像</li>
<li>MAINTAINER： 镜像维护者的姓名和邮箱地址</li>
<li>RUN： 容器构建时要运行的命令</li>
<li>EXPOSE：当前容器对外暴露的端口号</li>
<li>WORKDIR：进入容器终端时的目录</li>
<li>ENV：设置环境变量</li>
<li>ADD：拷贝文件到镜像中并对文件进行解压</li>
<li>COPY：拷贝文件到镜像中</li>
<li>VOLUME：容器数据卷</li>
<li>CMD：容器启动时运行的命令</li>
<li>ENTRYPOINT：指定容器启动时运行的命令</li>
<li>ONBUILD：父镜像被子镜像继承后父镜像的onbuild会被触发</li>
</ul>
</li>
<li><p>构建镜像</p>
<ul>
<li><code>docker build -f 文件路径 -t 镜像名:版本号 .</code></li>
</ul>
</li>
</ul>
<h1 id="docker-compose"><a href="#docker-compose" class="headerlink" title="docker-compose"></a>docker-compose</h1><ul>
<li>命令<ul>
<li>启动docker-compose.yml管理的容器 <code>docker-compose up  -d</code></li>
<li>关闭并删除容器 <code>docker-compose down</code></li>
<li>开启容器 <code>docker-compose start</code></li>
<li>关闭容器 <code>docker-compose stop</code></li>
<li>重启容器 <code>docker-compose restart</code></li>
<li>查看由docker-compse管理的容器 <code>docker-compose ps</code></li>
</ul>
</li>
</ul>
<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">version:</span> <span class="string">&#x27;3&#x27;</span></span><br><span class="line"><span class="attr">service:</span> </span><br><span class="line">  <span class="attr">ssm:</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">always</span>  <span class="comment"># </span></span><br><span class="line">    <span class="attr">build:</span>     <span class="comment"># 构建自定义镜像</span></span><br><span class="line">      <span class="attr">context:</span> <span class="string">../</span>   <span class="comment"># dockerfile文件所在的路径</span></span><br><span class="line">      <span class="attr">dockerfile:</span> <span class="string">Dockerfile</span>   <span class="comment"># Dockerfile文件名称</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">ssm:1.0</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">ssm</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="number">8080</span><span class="string">:8080</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">TZ:</span> <span class="string">Asia/Shanghai</span></span><br></pre></td></tr></table></figure>



<h1 id="部署SpringBoot项目"><a href="#部署SpringBoot项目" class="headerlink" title="部署SpringBoot项目"></a>部署SpringBoot项目</h1><p>1.将jar包上传到服务器</p>
<p>2.编写Dockerfile文件</p>
<figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">From</span> java:<span class="number">8</span></span><br><span class="line"><span class="keyword">MAINTAINER</span> xwt</span><br><span class="line"><span class="keyword">ADD</span><span class="language-bash"> wei-account-back-0.0.1-SNAPSHOT.jar /docker/app.jar</span></span><br><span class="line"><span class="keyword">ENTRYPOINT</span><span class="language-bash"> [<span class="string">&quot;nohup&quot;</span>, <span class="string">&quot;java&quot;</span>, <span class="string">&quot;-jar&quot;</span>, <span class="string">&quot;/docker/app.jar&quot;</span>, <span class="string">&quot;&amp;&quot;</span>]</span></span><br></pre></td></tr></table></figure>

<p>3.构建镜像 <code>docker build -t 镜像名:版本号 .</code></p>
<p>4.运行镜像 <code>docker run -d -p 7979:7979 -e TZ=&quot;Asia/Shanghai&quot; --name wei-account wei-account</code></p>

        
        
      
    </div>
    <footer class="article-footer">
      
        <div class="article-tag-wrap">
          

          
          


        </div>
      
      <!--  -->
      <!--  -->
    </footer>
  </div>
</article>


  <article id="post-移位运算符" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-inner">
    
    
    <div class="article-meta">
      
      <!-- <span class="article-date">
  <i class="fa fa-date"></i>
  <time class="dt-published" datetime="2023-02-07T06:39:34.000Z" itemprop="datePublished">2023年02月07日</time>
</span> -->
      
  <div class="article-category">
    <i class="fa fa-classify"></i>
    <a class="article-category-link" href="/wei-blog/categories/Java/">Java</a>
  </div>

      
      
<!-- <a href="/wei-blog/source/%E7%A7%BB%E4%BD%8D%E8%BF%90%E7%AE%97%E7%AC%A6/#comments" class="article-comment-link">
  
  <i class="fa fa-commt"></i>
  留言
</a> -->


    </div>
    <div class="e-content article-entry" itemprop="articleBody">
      
        <blockquote>
<p>移位运算符只作用于整形变量，分为两类，</p>
<p>​	第一类是 long 类型，long 类型长度为 8 字节 64 位；</p>
<p>​	第二类为 int 类，int 长度为 4 字节 32 位，short、byte、char在做移位之前会自动转换为int型</p>
</blockquote>
<h1 id="左移运算符"><a href="#左移运算符" class="headerlink" title="左移运算符"></a>左移运算符</h1><blockquote>
<p>运算规则：丢弃左边（高位）指定位数，右边（低位）补0</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">    <span class="type">int</span> <span class="variable">a</span> <span class="operator">=</span> <span class="number">10</span>;</span><br><span class="line">    <span class="type">int</span> <span class="variable">b</span> <span class="operator">=</span> a &lt;&lt; <span class="number">1</span>;</span><br><span class="line">    <span class="type">int</span> <span class="variable">c</span> <span class="operator">=</span> a &lt;&lt; <span class="number">29</span>;</span><br><span class="line">    <span class="comment">// 右移过程中符号位改变</span></span><br><span class="line">    <span class="type">int</span> <span class="variable">d</span> <span class="operator">=</span> a &lt;&lt; <span class="number">30</span>;</span><br><span class="line">    System.out.println(Integer.toBinaryString(a) + <span class="string">&quot; -- &quot;</span> + a);</span><br><span class="line">    System.out.println(Integer.toBinaryString(b) + <span class="string">&quot; -- &quot;</span> + b);</span><br><span class="line">    System.out.println(Integer.toBinaryString(c) + <span class="string">&quot; -- &quot;</span> + c);</span><br><span class="line">    System.out.println(Integer.toBinaryString(d) + <span class="string">&quot; -- &quot;</span> + d);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// int为32位，未达到长度时不丢弃位数</span></span><br><span class="line"><span class="comment">// 高位0不显示</span></span><br><span class="line"><span class="comment">// 1010 -- 10</span></span><br><span class="line"><span class="comment">// 10100 -- 20</span></span><br><span class="line"><span class="comment">// 1000000000000000000000000000000 -- 1073741824</span></span><br><span class="line"><span class="comment">// 10000000000000000000000000000000 -- -2147483648</span></span><br></pre></td></tr></table></figure>

<h1 id="右移运算符"><a href="#右移运算符" class="headerlink" title="右移运算符"></a>右移运算符</h1><blockquote>
<p>运算规则：丢弃右边（低位）指定位数，左边（高位）补上符号位的值</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">System.out.println(Integer.toBinaryString(-<span class="number">1</span>) + <span class="string">&quot; -- &quot;</span> + (-<span class="number">1</span> &gt;&gt; <span class="number">1</span>));</span><br><span class="line">System.out.println(Integer.toBinaryString(<span class="number">1</span>) + <span class="string">&quot; -- &quot;</span> + (<span class="number">1</span> &gt;&gt; <span class="number">1</span>));</span><br><span class="line"></span><br><span class="line"><span class="comment">// 填充的是符号位的值</span></span><br><span class="line"><span class="comment">// 11111111111111111111111111111111 -- -1</span></span><br><span class="line"><span class="comment">// 1 -- 0</span></span><br></pre></td></tr></table></figure>



<h1 id="无符号右移运算符"><a href="#无符号右移运算符" class="headerlink" title="无符号右移运算符"></a>无符号右移运算符</h1><blockquote>
<p>运算规则：与右移基本一致，唯一不同之处在于，在高位补位时，补0而非符号位的值，也就是说，无符号右移是忽略符号，最终结果一定是非负数。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">System.out.println(Integer.toBinaryString(-<span class="number">1</span>) + <span class="string">&quot; -- &quot;</span> + (-<span class="number">1</span> &gt;&gt;&gt; <span class="number">1</span>));</span><br><span class="line">System.out.println(Integer.toBinaryString(<span class="number">1</span>) + <span class="string">&quot; -- &quot;</span> + (<span class="number">1</span> &gt;&gt;&gt; <span class="number">1</span>));</span><br><span class="line"></span><br><span class="line"><span class="comment">// 11111111111111111111111111111111 -- 2147483647</span></span><br><span class="line"><span class="comment">// 1 -- 0</span></span><br></pre></td></tr></table></figure>
        
        
      
    </div>
    <footer class="article-footer">
      
        <div class="article-tag-wrap">
          

          
          


        </div>
      
      <!--  -->
      <!--  -->
    </footer>
  </div>
</article>


  <article id="post-注解的使用" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/wei-blog/source/%E6%B3%A8%E8%A7%A3%E7%9A%84%E4%BD%BF%E7%94%A8/">注解的使用</a>
    </h1>
  


      </header>
    
    <div class="article-meta">
      
      <!-- <span class="article-date">
  <i class="fa fa-date"></i>
  <time class="dt-published" datetime="2023-02-07T06:37:34.000Z" itemprop="datePublished">2023年02月07日</time>
</span> -->
      
  <div class="article-category">
    <i class="fa fa-classify"></i>
    <a class="article-category-link" href="/wei-blog/categories/Java/">Java</a>
  </div>

      
      
<!-- <a href="/wei-blog/source/%E6%B3%A8%E8%A7%A3%E7%9A%84%E4%BD%BF%E7%94%A8/#comments" class="article-comment-link">
  
  <i class="fa fa-commt"></i>
  留言
</a> -->


    </div>
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="自定义注解"><a href="#自定义注解" class="headerlink" title="自定义注解"></a>自定义注解</h1><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> CherryAnnotation &#123;</span><br><span class="line">	<span class="keyword">public</span> String <span class="title function_">name</span><span class="params">()</span>;</span><br><span class="line">	<span class="type">int</span> <span class="title function_">age</span><span class="params">()</span> <span class="keyword">default</span> <span class="number">18</span>;</span><br><span class="line">	<span class="type">int</span>[] array();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>定义注解类型元素时需要注意如下几点：</strong></p>
<ul>
<li>访问修饰符必须为public，不写默认为public；</li>
<li>该元素的类型只能是基本数据类型、String、Class、枚举类型、注解类型、一维数组；</li>
<li>该元素的名称一般定义为名词，如果注解中只有一个元素，请把名字起为value；</li>
<li>()不是定义方法参数的地方，也不能在括号中定义任何参数，仅仅只是一个特殊的语法；</li>
<li>default代表默认值，值必须和定义的类型一致；</li>
<li>如果没有默认值，代表后续使用注解时必须给该类型元素赋值。</li>
<li>如果注解本身只有一个注解类型元素，而且命名为value，那么在使用注解的时候可以直接使用：@注解名(注解值)，其等效于：@注解名(value &#x3D; 注解值)</li>
<li>如果注解中的某个注解类型元素是数组类型，在使用时又出现只需要填入一个值的情况，那么在使用注解时可以直接写为：@注解名(类型名 &#x3D; 类型值)，它和标准写法：@注解名(类型名 &#x3D; {类型值})等效</li>
</ul>
<h1 id="元注解"><a href="#元注解" class="headerlink" title="元注解"></a>元注解</h1><h2 id="Target"><a href="#Target" class="headerlink" title="@Target"></a>@Target</h2><blockquote>
<p>@Target注解，是专门用来限定某个自定义注解能够被应用在哪些Java元素上面的</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">enum</span> <span class="title class_">ElementType</span> &#123;</span><br><span class="line">    <span class="comment">/** 类，接口（包括注解类型）或枚举的声明 */</span></span><br><span class="line">    TYPE,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 属性的声明 */</span></span><br><span class="line">    FIELD,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 方法的声明 */</span></span><br><span class="line">    METHOD,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 方法形式参数声明 */</span></span><br><span class="line">    PARAMETER,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 构造方法的声明 */</span></span><br><span class="line">    CONSTRUCTOR,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 局部变量声明 */</span></span><br><span class="line">    LOCAL_VARIABLE,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 注解类型声明 */</span></span><br><span class="line">    ANNOTATION_TYPE,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 包的声明 */</span></span><br><span class="line">    PACKAGE</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>示例</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Target(&#123;ElementType.TYPE,ElementType.METHOD&#125;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> CherryAnnotation &#123;</span><br><span class="line">    String <span class="title function_">name</span><span class="params">()</span>;</span><br><span class="line">    <span class="type">int</span> <span class="title function_">age</span><span class="params">()</span> <span class="keyword">default</span> <span class="number">18</span>;</span><br><span class="line">    <span class="type">int</span>[] array();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="Retention"><a href="#Retention" class="headerlink" title="@Retention"></a>@Retention</h2><blockquote>
<p>用来修饰自定义注解的生命周期</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">enum</span> <span class="title class_">RetentionPolicy</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 注解将被编译器忽略掉</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    SOURCE,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 注解将被编译器记录在class文件中，但在运行时不会被虚拟机保留，这是一个默认的行为</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    CLASS,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 注解将被编译器记录在class文件中，而且在运行时会被虚拟机保留，因此它们能通过反射被读取到</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    RUNTIME</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>示例</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Retention(RetentionPolicy.RUNTIME)</span></span><br><span class="line"><span class="meta">@Target(&#123;ElementType.TYPE,ElementType.METHOD&#125;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> CherryAnnotation &#123;</span><br><span class="line">    String <span class="title function_">name</span><span class="params">()</span>;</span><br><span class="line">    <span class="type">int</span> <span class="title function_">age</span><span class="params">()</span> <span class="keyword">default</span> <span class="number">18</span>;</span><br><span class="line">    <span class="type">int</span>[] array();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="Documented"><a href="#Documented" class="headerlink" title="@Documented"></a>@Documented</h2><blockquote>
<p>用来指定自定义注解是否能随着被定义的java文件生成到JavaDoc文档当中</p>
</blockquote>
<h2 id="Inherited"><a href="#Inherited" class="headerlink" title="@Inherited"></a>@Inherited</h2><blockquote>
<p>指定某个自定义注解如果写在了父类的声明部分，那么子类的声明部分也能自动拥有该注解。@Inherited注解只对那些@Target被定义为ElementType.TYPE的自定义注解起作用。</p>
</blockquote>
<h1 id="通过反射获取注解"><a href="#通过反射获取注解" class="headerlink" title="通过反射获取注解"></a>通过反射获取注解</h1><p>注解</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Target(&#123;ElementType.FIELD&#125;)</span></span><br><span class="line"><span class="meta">@Retention(RetentionPolicy.RUNTIME)</span></span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> SetValue &#123;</span><br><span class="line">    String <span class="title function_">value</span><span class="params">()</span> <span class="keyword">default</span> <span class="string">&quot;default&quot;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>使用</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SetValue(value = &quot;xwt&quot;)</span></span><br><span class="line"><span class="keyword">private</span> String name;</span><br></pre></td></tr></table></figure>

<p>获取注解内容</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">Class&lt;?&gt; beanClass = bean.getClass();</span><br><span class="line">Field[] fields = beanClass.getDeclaredFields();</span><br><span class="line"><span class="keyword">for</span> (Field field : fields) &#123;</span><br><span class="line">    <span class="keyword">if</span> (field.isAnnotationPresent(SetValue.class)) &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;在&quot;</span> + beanName + <span class="string">&quot;中的&quot;</span> + field.getName() + <span class="string">&quot;属性发现注解&quot;</span>);</span><br><span class="line">        <span class="type">SetValue</span> <span class="variable">annotation</span> <span class="operator">=</span> field.getAnnotation(SetValue.class);</span><br><span class="line">        <span class="type">String</span> <span class="variable">value</span> <span class="operator">=</span> annotation.value();</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            field.setAccessible(<span class="literal">true</span>);</span><br><span class="line">            field.set(bean, value);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IllegalAccessException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

        
        
      
    </div>
    <footer class="article-footer">
      
        <div class="article-tag-wrap">
          

          
          


        </div>
      
      <!--  -->
      <!--  -->
    </footer>
  </div>
</article>



    <nav id="page-nav">

<span class="page-number current">1</span><a class="page-number" href="/wei-blog/page/2/">2</a><a class="page-number" href="/wei-blog/page/3/">3</a><a class="page-number" href="/wei-blog/page/4/">4</a><a class="extend next" rel="next" href="/wei-blog/page/2/">下一页</a>
</nav>


</section>
        
          <aside id="sidebar">
  
    
  <div class="widget-wrap">
    <h3 class="widget-title"><i class="fa fa-classify"></i> 分类</h3>
    <div class="widget">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/wei-blog/categories/Docker/">Docker</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/wei-blog/categories/Java/">Java</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/wei-blog/categories/RabbitMQ/">RabbitMQ</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/wei-blog/categories/Redis/">Redis</a><span class="category-list-count">9</span></li><li class="category-list-item"><a class="category-list-link" href="/wei-blog/categories/Spring/">Spring</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/wei-blog/categories/SpringBoot/">SpringBoot</a><span class="category-list-count">13</span><ul class="category-list-child"><li class="category-list-item"><a class="category-list-link" href="/wei-blog/categories/SpringBoot/RabbitMQ/">RabbitMQ</a><span class="category-list-count">1</span></li></ul></li><li class="category-list-item"><a class="category-list-link" href="/wei-blog/categories/SpringSecurity/">SpringSecurity</a><span class="category-list-count">1</span></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title"><i class="fa fa-tag"></i> 标签</h3>
    <div class="widget">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/wei-blog/tags/AOP/" rel="tag">AOP</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/wei-blog/tags/JWT/" rel="tag">JWT</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/wei-blog/tags/MyBatis/" rel="tag">MyBatis</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/wei-blog/tags/MyBatisPlus/" rel="tag">MyBatisPlus</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/wei-blog/tags/%E6%8B%A6%E6%88%AA%E5%99%A8/" rel="tag">拦截器</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/wei-blog/tags/%E8%B7%A8%E5%9F%9F/" rel="tag">跨域</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/wei-blog/tags/%E8%BF%90%E8%A1%8C%E9%94%99%E8%AF%AF/" rel="tag">运行错误</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/wei-blog/tags/%E9%80%BB%E8%BE%91/" rel="tag">逻辑</a><span class="tag-list-count">2</span></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title"><i class="fa fa-posts"></i> 最新文章</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/wei-blog/source/%E5%9F%BA%E4%BA%8ERedis%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81/">基于Redis的分布式锁</a>
          </li>
        
          <li>
            <a href="/wei-blog/source/SpringBoot%E5%AE%9E%E7%8E%B0%E6%8E%A5%E5%8F%A3%E9%99%90%E6%B5%81/">SpringBoot实现接口限流</a>
          </li>
        
          <li>
            <a href="/wei-blog/source/%E7%BC%93%E5%AD%98%E7%A9%BF%E9%80%8F%E3%80%81%E7%BC%93%E5%AD%98%E9%9B%AA%E5%B4%A9%E3%80%81%E7%BC%93%E5%AD%98%E5%87%BB%E7%A9%BF/">(no title)</a>
          </li>
        
          <li>
            <a href="/wei-blog/source/SpringBoot%E6%95%B4%E5%90%88RabbitMQ/">SpringBoot整合RabbitMQ</a>
          </li>
        
          <li>
            <a href="/wei-blog/source/Redis%E4%B9%8BZSet/">(no title)</a>
          </li>
        
      </ul>
    </div>
  </div>


  
</aside>
        
      </div>
      <a id="totop" href="#top"></a>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      <!-- <p>
        <a href="/wei-blog/sitemap.xml">网站地图</a>
        <span> | </span><a href="/wei-blog/atom.xml">订阅本站</a>
        <span> | </span><a href="/wei-blog/about/">联系博主</a>
      </p> -->
      
      <p>
        <span>Copyright &copy; 2023 xueweitao.</span>
        <!-- <span>Theme by <a href="https://github.com/chaooo/hexo-theme-BlueLake/" target="_blank">BlueLake.</a></span>
        <span>Powered by <a href="https://hexo.io/" target="_blank">Hexo.</a></span> -->
      </p>
    </div>
  </div>
</footer>

    </div>
  </div>
  
<script src="/wei-blog/js/jquery-3.4.1.min.js"></script>


<script src="/wei-blog/js/search.json.js"></script>




<script src="/wei-blog/js/script.js"></script>












  



</body>
</html>